from langchain.agents import tool
from typing import Union
from pydantic import BaseModel, Field

# class MathInput(BaseModel):
#     expression: str = Field(..., description="数学表达式，如：15*3+8/2-5")

@tool(
    description="""
        计算器：执行精确的四则运算（支持浮点数和整数的加减乘除等）
        1.支持括号运算，支持小数和整数的运算
        2.除法运算结果为0时，返回"除零错误"
        3.除法运算结果为非数字时，返回"计算错误"
        参数：
            expression：数学表达式，如：15*3+8/2-5（必传）
        返回结果：
            计算结果（float）或错误信息（str）
        输入示例：(18.5 + 3.7) * 2.5 / 3 - 5
        使用示例：calculate_expression.invoke("(18.5 + 3.7) * 2.5 / 3 - 5")
        输出示例：13.5
    """,
    # args_schema=MathInput,
    # return_direct=True  # 直接返回结果不经过LLM处理
)
def calculate_expression(expression: str) -> Union[float, str]:
    """安全执行数学运算的三种模式"""
    print("正在执行【表达式计算】...", expression)
    # 模式1：表达式预处理
    expr = expression.replace(' ', '').replace('×', '*').replace('÷', '/')
    
    # 模式2：使用numexpr库（更安全）
    try:
        import numexpr
        return float(numexpr.evaluate(expr))
    except:
        pass
        
    # 模式3：原生计算（带异常捕获）
    try:
        return eval(expr, {"__builtins__": None}, {})
    except ZeroDivisionError:
        return "除零错误"
    except Exception as e:
        return f"计算错误：{str(e)}"

# 使用示例
# print(calculate_expression.invoke("85 + 88 + 90 + 87 + 84 + 82 + 80 + 78 + 89 + 91"))  # 输出：55.5
# print(calculate_expression.invoke("10 / 0"))             # 输出：除零错误
@tool(
    description="""
        数值比较工具：比较多个数值的大小，返回最大值及完整比较表达式
        功能说明：
        1. 支持比较2个及以上任意数量的数字
        2. 自动过滤非数字类型参数
        3. 返回最大数值及降序排列的表达式
        参数说明：
            numbers：要比较的多个数字（至少2个，必传）
        返回结果：
            字符串格式的比较结果，包含最大值和完整比较式
        输入示例1：5, 3, 7
        调用示例：compare_sizes.invoke({"numbers": [5, 3, 7]})
        输出示例："最大值：7 (7 > 5 > 3)"
        
        输入示例2：15, 8.5, 12, 20.3
        调用示例：compare_sizes.invoke({"numbers": [15, 8.5, 12, 20.3]})
        输出示例："最大值：20.3 (20.3 > 15 > 12 > 8.5)"
    """,
)
def compare_sizes(numbers: list[Union[float, int]]) -> str:
    print(f"正在执行【数值比较工具】... 参数：{numbers}")
    
    # 参数校验
    if len(numbers) < 2:
        return "错误：至少需要两个数字进行比较"
    
    # 类型过滤（自动跳过非数字类型）
    valid_numbers = [num for num in numbers if isinstance(num, (int, float))]
    if len(valid_numbers) != len(numbers):
        return "错误：包含非数字类型参数"
    
    # 降序排序并生成比较表达式
    sorted_nums = sorted(valid_numbers, reverse=True)
    comparison = " > ".join(map(str, sorted_nums))
    
    # 构造结果字符串
    return f"最大值：{sorted_nums[0]} ({comparison})"

# print(compare_sizes.invoke({"numbers": [9, 3.14, 15, 7, 12.8]}))  

@tool(
    description="""
        区间判断工具：判断多个数字是否在指定数值区间内
        功能说明：
        1. 支持同时判断多个数字（至少2个）
        2. 自动处理上下限大小顺序
        3. 返回每个数字的判断结果和最终结论
        参数说明：
            lower：区间下限（必传）
            upper：区间上限（必传）
            numbers：要判断的多个数字（至少2个，必传）
        返回结果：
            字符串格式的判断结果，包含每个数字的状态和最终结论
        输入示例1：5, 10, [7, 12, 9]
        调用示例：check_range.invoke({"lower": 5, "upper": 10, "numbers": [7, 12, 9]})
        输出示例："结果：7(在区间内) 12(超出区间) 9(在区间内) | 结论：部分数字超出范围"
        
        输入示例2：15, 20, [16, 18, 19]
        调用示例：check_range.invoke({"lower": 15, "upper": 20, "numbers": [16, 18, 19]})
        输出示例："结果：16(在区间内) 18(在区间内) 19(在区间内) | 结论：所有数字符合要求"
    """,
    # return_direct=True
)
def check_range(lower: Union[float, str], upper: Union[float, str], numbers: list[Union[float, str]]) -> str:
    print(f"正在执行【区间判断工具】... 参数：{lower}-{upper}, 数字：{numbers}")
    
    # 类型转换函数
    def convert_to_float(value: Union[str, float]) -> float:
        try:
            return float(value)
        except (ValueError, TypeError):
            raise ValueError(f"无效数值参数：{repr(value)}")

    try:
        # 转换所有参数为float
        lower_num = convert_to_float(lower)
        upper_num = convert_to_float(upper)
        numbers_list = [convert_to_float(n) for n in numbers]
    except ValueError as e:
        return f"参数错误：{str(e)}"

    # 参数数量校验
    if len(numbers_list) < 2:
        return "错误：需要至少两个判断数字"
    
    # 自动处理上下限顺序
    min_val, max_val = sorted([lower_num, upper_num])
    
    # 判断每个数字状态
    results = []
    all_in_range = True
    for n in numbers_list:
        status = "在区间内" if min_val <= n <= max_val else "超出区间"
        if status == "超出区间":
            all_in_range = False
        results.append(f"{n}({status})")
    
    # 构建结论
    conclusion = "所有数字符合要求" if all_in_range else "部分数字超出范围"
    return f"结果：{' '.join(results)} | 结论：{conclusion}"

# print(check_range.invoke({"lower": "10", "upper": 5, "numbers": ["7", 8, 12.5]}))
# # 结果：7.0(超出区间) 8.0(在区间内) 12.5(在区间内) | 结论：部分数字超出范围

# print(check_range.invoke({"lower": "a", "upper": 5, "numbers": [7]}))
# # 参数错误：无效数值参数：'a'

# print(check_range.invoke({"lower": 10, "upper": 20, "numbers": ["15", "25%"]}))
# # 参数错误：无效数值参数：'25%'

count_tools = [
    calculate_expression,
    compare_sizes,
    check_range
]